package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.sound.midi.Track;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;
	@Autowired
	private VodService vodService;

	@Autowired
	private TrackStatMapper trackStatMapper;
	@Autowired
	private AlbumStatMapper albumStatMapper;

	@Autowired
	private AlbumInfoMapper albumInfoMapper;

	@Autowired
	private UserInfoFeignClient userInfoFeignClient;


    @Tag(name = "上传声音")
	@SneakyThrows
	@Override
	public UploadTrackVo uploadTrack(MultipartFile file) {

		return vodService.uploadTrack(file);
	}

	@Tag(name = "新增声音")
	@Transactional
	@Override
	public void saveTrackInfo(TrackInfoVo trackInfoVo) {

		//获取用户id
		Long userId = AuthContextHolder.getUserId();
		//保存声音基本数据
		TrackInfo trackInfo = new TrackInfo() ;
		trackInfo.setUserId(userId);
		trackInfo.setAlbumId(trackInfoVo.getAlbumId());
		trackInfo.setTrackTitle(trackInfoVo.getTrackTitle());
		trackInfo.setTrackIntro(trackInfoVo.getTrackIntro());
		trackInfo.setTrackRichIntro(trackInfoVo.getTrackRichIntro());
		trackInfo.setCoverUrl(trackInfoVo.getCoverUrl());
		trackInfo.setIsOpen(trackInfoVo.getIsOpen());
		trackInfo.setSource(SystemConstant.TRACK_SOURCE_UPLOAD);
		trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);

		//设置排序字段的值
		LambdaQueryWrapper<TrackInfo> lambdaQueryWrapper =new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId());
		//倒序查询取最大的一条数据
		lambdaQueryWrapper.orderByDesc(TrackInfo::getOrderNum);
		lambdaQueryWrapper.last("limit 1");
		//查询一条数据
		TrackInfo dbtrackInfo1 = trackInfoMapper.selectOne(lambdaQueryWrapper);
		//判断原来有值+1 没值设为1
		if(dbtrackInfo1 != null){
			trackInfo.setOrderNum(dbtrackInfo1.getOrderNum()+1);
		}else {
			trackInfo.setOrderNum(1);
		}
		//媒体文件的值
		//根据id从腾讯云中获取数据 用TrackMediaInfoVo封装
		TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId()) ;
		trackInfo.setMediaDuration(new BigDecimal(trackMediaInfoVo.getDuration()));
		trackInfo.setMediaFileId(trackInfoVo.getMediaFileId());
		trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
		trackInfo.setMediaSize(trackMediaInfoVo.getSize());
		trackInfo.setMediaType(trackMediaInfoVo.getType());

		// 保存声音数据
		trackInfoMapper.insert(trackInfo) ;

		//初始化声音的统计数据
		this.saveTrackStat(trackInfo.getId() , SystemConstant.TRACK_STAT_PLAY);
		this.saveTrackStat(trackInfo.getId() , SystemConstant.TRACK_STAT_COLLECT);
		this.saveTrackStat(trackInfo.getId() , SystemConstant.TRACK_STAT_PRAISE);
		this.saveTrackStat(trackInfo.getId() , SystemConstant.TRACK_STAT_COMMENT);

		//修改album_info中的数据
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		Integer count = albumInfo.getIncludeTrackCount();//此专辑所包含的专辑声音数量
		albumInfo.setIncludeTrackCount(count+1);//声音数量+1
		albumInfoMapper.updateById(albumInfo);//修改数据

	}

	@Tag(name = "查询当前用户声音分页列表")
	@Override
	public IPage<TrackListVo> findUserTrackPage(TrackInfoQuery trackInfoQuery, Integer pageNo, Integer pageSize) {

		// 获取当前登录用户的id
		Long userId = AuthContextHolder.getUserId();
		trackInfoQuery.setUserId(userId);
		// 创建Page对象，封装分页的参数
		IPage<TrackListVo> iPage = new Page<>(pageNo, pageSize);

		// 调用Mapper接口方法完成分页查询
		IPage<TrackListVo> ipage= trackInfoMapper.findUserTrackPage(iPage, trackInfoQuery);
		return ipage;
	}

	@Override
	public void updateTrackInfo(Integer id ,TrackInfoVo trackInfoVo) {
		//根据声音id查询声音数据
		TrackInfo trackInfo = trackInfoMapper.selectById(id);
		String infoVoMediaFileId = trackInfoVo.getMediaFileId();//从前端传入的数据中查找文件id
		String dbMediaFileId = trackInfo.getMediaFileId();//从数据库中查找文件id
		BeanUtils.copyProperties(trackInfoVo, trackInfo);//属性拷贝
		if(!infoVoMediaFileId.equals(dbMediaFileId)){
			//两个id不相等说明声音文件已被修改，则要从云点播中获取新的数据并修改数据库中文件时长等数据
			TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(infoVoMediaFileId);//获取最新的文件信息
			trackInfo.setMediaSize(trackMediaInfoVo.getSize());
			trackInfo.setMediaType(trackMediaInfoVo.getType());
			trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
			trackInfo.setMediaDuration(new BigDecimal(trackMediaInfoVo.getDuration()));
		}
		trackInfoMapper.updateById(trackInfo);
	}



	@Override
	public void removeTrackInfo(Long trackId) {
		// 0、根据声音的id查询声音数据
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);

		// 1、根据声音的id删除声音的基本数据
		trackInfoMapper.deleteById(trackId) ;

		// 2、根据声音的id删除声音的统计数据
		LambdaQueryWrapper<TrackStat> trackStatLambdaQueryWrapper = new LambdaQueryWrapper<TrackStat>() ;
		trackStatLambdaQueryWrapper.eq(TrackStat::getTrackId, trackId) ;
		trackStatMapper.delete(trackStatLambdaQueryWrapper) ;

		// 3、修改album_info表中的数据(include_track_count)
		Long albumId = trackInfo.getAlbumId();
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		Integer includeTrackCount = albumInfo.getIncludeTrackCount();
		albumInfo.setIncludeTrackCount(includeTrackCount - 1);
		albumInfoMapper.updateById(albumInfo) ;

		// 4、删除云点播服务中的媒体数据
		vodService.deleteMediaInfo(trackInfo.getMediaFileId());
	}

	// 初始化声音的统计数据
	private void saveTrackStat(Long trackId , String statType) {
		TrackStat trackStat = new TrackStat();
		trackStat.setTrackId(trackId);
		trackStat.setStatType(statType);
		trackStat.setStatNum(0);
		trackStatMapper.insert(trackStat) ;
	}





	@Override
	public IPage<AlbumTrackListVo> findAlbumTrackPage(Long albumId, Long pageNo, Long pageSize) {
		//创建page对象，封装参数
		Page<AlbumTrackListVo> page = new Page<>(pageNo,pageSize);
		IPage<AlbumTrackListVo> iPage = trackInfoMapper.findAlbumTrackPage(page,albumId);//进行分页查询
		List<AlbumTrackListVo> pageRecords = page.getRecords();//获取当前页对象
		//根据专辑id查询专辑
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		//判断用户是否登录
		Long userId = AuthContextHolder.getUserId();
		if (userId == null){//用户未登录
			//判断是否为免费声音，需要获取专辑信息
			String payType = albumInfo.getPayType();
			if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(payType)){//此声音不免费
				//过滤筛选掉试听声音，将其余声音添加付费按钮
				pageRecords.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
						.forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
			}

		}else {//用户已登录
			//判断是否为vip免费声音
			String payType = albumInfo.getPayType();
			if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(payType)){//vip免费
				//判断是否为vip用户
				Result<UserInfo> userInfo = userInfoFeignClient.findUserInfoById(albumInfo.getUserId());
				Integer isVip = userInfo.getData().getIsVip();
				if (isVip ==0 ){//非vip用户
					//过滤掉试听声音，将剩余声音添加付费按钮
					pageRecords.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
							.forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
				}else {//为vip用户
					//判断vip是否过期
					Date vipExpireTime = userInfo.getData().getVipExpireTime();//获取vip过期时间
					//当系统时间大于过期时间则说明vip已过期
					if (vipExpireTime.before(new Date())){//vip已过期
						//过滤掉试听声音，将剩余声音添加付费按钮
						pageRecords.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
								.forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
					}
				}

			}else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(payType)){//付费专辑

				//过滤掉试听声音，将剩余声音提取id进一步判断是否购买过
				List<Long> collect = pageRecords.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
						.map(albumTrackListVo -> albumTrackListVo.getTrackId()).collect(Collectors.toList());

				// 判断用户是否购买过这些声音
				/**
				 * 后期如果用户购买了专辑或者某些声音，此时会在ting_user数据库中的user_paid_album、user_paid_track表中记录购买信息
				 * user_paid_album表中记录的是专辑购买的信息
				 * user_paid_track表中记录的是声音购买的信息
				 * Feign-album-service调用user-service中的接口判断用户是否购买过这些声音
				 */

			}

		}
		return page;
	}

	@Override
	public void trackStatUpdata(TrackStatMqVo trackStatMqVo) {
		//更新声音播放量
		String statType = trackStatMqVo.getStatType();//获取所有统计维度
		if (SystemConstant.ALBUM_STAT_PLAY.equals(statType)){//获取播放量统计维度

			//更新声音的播放量
			LambdaQueryWrapper<TrackStat> lambdaQueryWrapper = new LambdaQueryWrapper<>();
			lambdaQueryWrapper.eq(TrackStat::getTrackId, trackStatMqVo.getTrackId());
			lambdaQueryWrapper.eq(TrackStat::getStatType, SystemConstant.TRACK_STAT_PLAY);
			TrackStat trackStat = trackStatMapper.selectOne(lambdaQueryWrapper);
			trackStat.setStatNum(trackStat.getStatNum()+trackStatMqVo.getCount());
			trackStatMapper.updateById(trackStat);

			//更新专辑播放量
			LambdaQueryWrapper<AlbumStat> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
			lambdaQueryWrapper1.eq(AlbumStat::getAlbumId, trackStatMqVo.getAlbumId());
			lambdaQueryWrapper1.eq(AlbumStat::getStatType, SystemConstant.ALBUM_STAT_PLAY);
			AlbumStat albumStat = albumStatMapper.selectOne(lambdaQueryWrapper1);
			albumStat.setStatNum(albumStat.getStatNum()+trackStatMqVo.getCount());
			albumStatMapper.updateById(albumStat);
			//TODO:需要更新es索引库中的数据

		}
	}

	@Override
	public TrackStatVo getTrackStatVo(Long trackId) {
		TrackStatVo trackStatVo = trackStatMapper.selectTrackStat(trackId);
		return null;
	}

	@Override
	public List<TrackPayVo> findUserTrackPaidList(Long trackId) {
		//根据声音Id查询声音数据
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);

		//从声音数据中获取专辑Id
		Long albumId = trackInfo.getAlbumId();
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);

		//查询当前用户购买的声音列表
		Result<List<Long>> userPaidTrackList = userInfoFeignClient.findUserPaidTrackList(albumId);
		List<Long> userPaidTrackListData  = userPaidTrackList.getData();

		//查询当前专辑声音的OrderNum大于用户点击的声音列表
		LambdaQueryWrapper<TrackInfo>lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(TrackInfo::getAlbumId,albumId);
		lambdaQueryWrapper.gt(TrackInfo::getOrderNum, trackInfo.getOrderNum());
		lambdaQueryWrapper.orderByAsc(TrackInfo::getOrderNum);
		lambdaQueryWrapper.select(TrackInfo::getId);//指定查询列
		List<TrackInfo> trackInfoList = trackInfoMapper.selectList(lambdaQueryWrapper);
		//声音列表
		List<Long> trackInfoIds = trackInfoList.stream().map(Track -> Track.getId()).collect(Collectors.toList());
		//从第四部中筛选用户未购买的声音列表
		List<Long> ids = new ArrayList<>();

		if(CollectionUtils.isEmpty(userPaidTrackListData)){
			//没有未购买的声音列表
			ids = trackInfoIds;
		}else {
			//有未购买的声音列表
		    ids = trackInfoIds.stream().filter(id -> !userPaidTrackListData.contains(id)).collect(Collectors.toList());
		}

		//从第五步中得到的声音列表构建分页列表
		List<TrackPayVo> trackPayVoList = new ArrayList<>();

		//本集
		TrackPayVo trackPayVo = new TrackPayVo();
		trackPayVo.setName("本集");
		trackPayVo.setPrice(albumInfo.getPrice());
		trackPayVo.setTrackCount(0);
		trackPayVoList.add(trackPayVo);

		//以10集为单位构建分集列表
		int count = ids.size();
		if (ids.size()>0 && ids.size()<=10){
			TrackPayVo trackPayVoAfterCount  = new TrackPayVo();
			trackPayVoAfterCount.setName("后"+count+"集");
			BigDecimal price  = albumInfo.getPrice().multiply(new BigDecimal(count)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2,BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(count);
		}

		if(count > 10) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
			trackPayVoAfterCount.setName("后10集" );
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(10)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(10);
			trackPayVoList.add(trackPayVoAfterCount) ;
		}

		// 大于10
		if(count > 10 && count <= 20) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
			trackPayVoAfterCount.setName("后" + count + "集" );
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(count);
			trackPayVoList.add(trackPayVoAfterCount) ;
		}

		// 大于20
		if (count > 20) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
			trackPayVoAfterCount.setName("后20集" );
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(20)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(20);
			trackPayVoList.add(trackPayVoAfterCount) ;
		}

		if(count > 20 && count <= 30) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
			trackPayVoAfterCount.setName("后" + count + "集" );
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(count);
			trackPayVoList.add(trackPayVoAfterCount) ;
		}

		// 大于30
		if(count > 30) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
			trackPayVoAfterCount.setName("后30集" );
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(40)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(30);
			trackPayVoList.add(trackPayVoAfterCount) ;
		}

		if(count > 30 && count <= 50) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
			trackPayVoAfterCount.setName("后" + count + "集" );
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(count);
			trackPayVoList.add(trackPayVoAfterCount) ;
		}

		// 大于50
		if(count > 50) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
			trackPayVoAfterCount.setName("后50集" );
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(50)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(50);
			trackPayVoList.add(trackPayVoAfterCount) ;
		}

		return trackPayVoList;
	}

	@Override
	public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount) {
		// 创建一个List集合对象，用来存储查询的结果数据
		List<TrackInfo> trackInfoList = new ArrayList<>() ;

		// 根据声音的id查询声音数据
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);

		// 获取专辑的id
		Long albumId = trackInfo.getAlbumId();

		// 从track_info表中查询需要购买的声音列表(需要排除已经购买过的声音id)
		// select * from track_info where album_id = ? and order_num > ? and id not in(....) limit ?
		Result<List<Long>> userPaidTrackList = userInfoFeignClient.findUserPaidTrackList(albumId);
		List<Long> userPaidTrackIds = userPaidTrackList.getData();

		// 判断trackCount是否大于0
		if(trackCount > 0) {

			LambdaQueryWrapper<TrackInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>() ;
			lambdaQueryWrapper.eq(TrackInfo::getAlbumId, albumId) ;
			lambdaQueryWrapper.gt(TrackInfo::getOrderNum , trackInfo.getOrderNum()) ;
			lambdaQueryWrapper.orderByAsc(TrackInfo::getOrderNum) ;
			if(!CollectionUtils.isEmpty(userPaidTrackIds)) {
				lambdaQueryWrapper.notIn(TrackInfo::getId, userPaidTrackIds) ;
			}
			lambdaQueryWrapper.last("limit " + trackCount) ;
			trackInfoList = trackInfoMapper.selectList(lambdaQueryWrapper);

		}else {		// 购买的是本集
			trackInfoList.add(trackInfo) ;
		}

		return trackInfoList;
	}
}
